/* 
 * Spring mixin mybatis frame code general
 * Fu(iknoweth@yahoo.com) All rights reserved 
 * 
 */
package com.pricl.biz.file.service;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.fileupload.disk.DiskFileItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectResult;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.vod.model.v20170321.CreateUploadVideoRequest;
import com.aliyuncs.vod.model.v20170321.CreateUploadVideoResponse;
import com.aliyuncs.vod.model.v20170321.GetVideoPlayAuthRequest;
import com.aliyuncs.vod.model.v20170321.GetVideoPlayAuthResponse;
import com.aliyuncs.vod.model.v20170321.RefreshUploadVideoRequest;
import com.aliyuncs.vod.model.v20170321.RefreshUploadVideoResponse;
import com.pricl.biz.file.api.IFileHandler;
import com.pricl.biz.file.constant.FileStatusConstant;
import com.pricl.biz.file.dao.FileInfoDao;
import com.pricl.biz.file.entity.FileInfo;
import com.pricl.biz.util.OSSUtils;
import com.pricl.frame.common.utils.DateUtils;
import com.pricl.frame.common.utils.Utils;
import com.pricl.frame.core.E;
import com.pricl.frame.core.web.Helper;

import it.sauronsoftware.jave.Encoder;
import it.sauronsoftware.jave.EncoderException;
import it.sauronsoftware.jave.InputFormatException;
import it.sauronsoftware.jave.MultimediaInfo;

/**
 * <p>
 * <strong>附件信息表</strong>Biz Service
 * </p>
 *
 */
@Service
public class FileService {

	@Autowired
	FileInfoDao dao;

	@Resource(name = "fileHandler")
	private IFileHandler handler;

	private String[] formatName(String name) {
		if (name == null || name.isEmpty()) {
			return new String[] { "", "" };
		}
		int lastDot = name.lastIndexOf('.');
		if (lastDot == -1) {
			return new String[] { "", "" };
		}
		return new String[] { name.substring(0, lastDot), name.substring(lastDot + 1) };
	}

	/**
	 * <p>
	 * 保存数据
	 * </p>
	 * 
	 * @param item
	 */
	public void upload(FileInfo item, InputStream in, long length) throws IOException {
		if (item.getId() == null || item.getId().isEmpty()) {
			item.setId(Utils.uuid());
		}
		String[] names = formatName(item.getOname());
		if (item.getName() == null || item.getName().isEmpty()) {
			item.setName(names[0]);
		}
		item.setExtName(names[1]);
		if(item.getExtName().equals("apk")){
			item.setPath("/resource/apk/");
		}else if(item.getExtName().equals("mp3")){
			// 文件路径
			item.setPath("/resource/audio/" + DateUtils.format(new Date(), "yy/MM/dd"));
		}else {
			item.setPath("/resource/img/" + DateUtils.format(new Date(), "yy/MM/dd"));
		}
		
		// 创建日期
		item.setCreatedDt(new Date());
		// 状态
		item.setStatus(FileStatusConstant.normal);
		
		OSSClient oSSClient = OSSUtils.getOSSClient();
		String resultStr  = OSSUtils.uploadObject2OSS2(oSSClient, item, in, length);
		if(resultStr != null){
			dao.insert(item);
		}
		// 保存文件，若存在转换文件，则返回转换文件的信息列表
		/*FileInfo[] files = handler.save(item, in, length);
		if (files != null && files.length > 0) {
			for (FileInfo file : files) {
				dao.insert(file);
			}
		}*/
	}

	/**
	 * <p>
	 * 删除数据
	 * </p>
	 * 
	 * @param id
	 */
	public void delete(String id) {
		// 修改状态为删除
		dao.updateStatus(id, FileStatusConstant.deleted);
	}

	/**
	 * <p>
	 * 获取唯一数据
	 * </p>
	 * 
	 * @param id
	 * @return AppFile
	 */
	public FileInfo findOne(String id) {
		return dao.findOne(id);
	}

	/**
	 * <p>
	 * 根据类型获取数据TODO String type >> Integer type
	 * </p>
	 * 
	 * @param oid
	 * @param type
	 * @return
	 */
	public FileInfo findByType(String oid, Integer type) {
		FileInfo file = dao.findByType(oid, type);
		if (file == null) {
			file = dao.findOne(oid);
		}
		return file;
	}

	/**
	 * <p>
	 * 保存文件的关联业务信息
	 * </p>
	 * 
	 * @param file
	 * @param type
	 * @param bid
	 * @param isSingle
	 */
	public void saveLink(String file, String type, String bid, boolean isSingle) {
		if (isSingle) {
			dao.deleteLink(type, bid);
		}
		dao.insertLink(file, type, bid);
	}

	/**
	 * <p>
	 * 根据业务信息获取文件列表
	 * </p>
	 * 
	 * @param type
	 * @param bid
	 * @return
	 */
	public List<FileInfo> findLink(String type, String bid) {
		return dao.findLink(type, bid);
	}

	/**
	 * 
	 * <p>
	 * 根据文件id获取文件信息
	 * </p>
	 * 
	 * @param id
	 * @return
	 */
	public File getFile(String id) {
		FileInfo item = dao.findOne(id);
		if (item == null) {
			throw new E("文件已丢失");
		}
		return getFile(item);
	}

	/**
	 * 
	 * <p>
	 * 根据文件信息获取文件
	 * </p>
	 * 
	 * @param item
	 * @return
	 */
	public File getFile(FileInfo item) {
		String sdir = Helper.getProp("file.saveDir");
		if (sdir == null || sdir.isEmpty()) {
			ApplicationContext ac = Helper.getApplicationContext();
			if (ac != null && ac instanceof WebApplicationContext) {
				sdir = ((WebApplicationContext) ac).getServletContext().getRealPath("/");
			}
			if (sdir == null || sdir.isEmpty()) {
				sdir = System.getProperty("webapp.root");
			}
			if (sdir == null || sdir.isEmpty()) {
				throw new RuntimeException("没有指定上传路径");
			}
		}
		System.out.println(String.format("%s%s%s%s", sdir, item.getPath(), File.separator, item.getFileName()));
		File file = new File(String.format("%s%s%s%s", sdir, item.getPath(), File.separator, item.getFileName()));
		return file;
	}

	/**
	 * 
	 * <p>
	 * 获取文件路径
	 * </p>
	 * 
	 * @param item
	 * @return
	 */
	public String getFilePath(FileInfo item) {
		String sdir = Helper.getProp("file.saveDir");
		if (sdir == null || sdir.isEmpty()) {
			ApplicationContext ac = Helper.getApplicationContext();
			if (ac != null && ac instanceof WebApplicationContext) {
				sdir = ((WebApplicationContext) ac).getServletContext().getRealPath("/");
			}
			if (sdir == null || sdir.isEmpty()) {
				sdir = System.getProperty("webapp.root");
			}
			if (sdir == null || sdir.isEmpty()) {
				throw new RuntimeException("没有指定上传路径");
			}
		}
		return String.format("%s%s%s%s", sdir, item.getPath(), File.separator, item.getName());
	}
	
	//上传并返回上传成功以后的路径
	public FileInfo uploadToGetPath(FileInfo item, InputStream in, long length) {
		if (item.getId() == null || item.getId().isEmpty()) {
			item.setId(Utils.uuid());
		}
		String[] names = formatName(item.getOname());
		if (item.getName() == null || item.getName().isEmpty()) {
			item.setName(names[0]);
		}
		item.setExtName(names[1]);
		// 文件路径
		item.setPath("/resource/" + DateUtils.format(new Date(), "yyyy/MM/dd"));
		// 创建日期
		item.setCreatedDt(new Date());
		// 状态
		item.setStatus(FileStatusConstant.normal);
		OSSClient oSSClient = OSSUtils.getOSSClient();
		String resultStr = OSSUtils.uploadObject2OSS2(oSSClient, item, in, length);
		if(resultStr != null){
			dao.insert(item);
		}
		// 保存文件，若存在转换文件，则返回转换文件的信息列表
		/*FileInfo[] files = handler.save(item, in, length);
		if (files != null && files.length > 0) {
			for (FileInfo file : files) {
				dao.insert(file);
			}
		}*/
		return item;
	}
	
	//获取视频、音频文件的时长
	private  long  getDuration(MultipartFile  file){
		 long duration = 0;//视、音频长度，秒
		/* CommonsMultipartFile cf= (CommonsMultipartFile)file;
         DiskFileItem fi = (DiskFileItem)cf.getFileItem();
         File source = fi.getStoreLocation(); 
         Encoder encoder = new Encoder();
         MultipartFile m = encoder.getInfo(source);
         long ls = m.getDuration();*/
         //duration = ls/1000;
		return duration;
	}
	
	public void upload(FileInfo item, InputStream in, long length,MultipartFile file) throws IOException {
		if (item.getId() == null || item.getId().isEmpty()) {
			item.setId(Utils.uuid());
		}
		String[] names = formatName(item.getOname());
		if (item.getName() == null || item.getName().isEmpty()) {
			item.setName(names[0]);
		}
		item.setExtName(names[1]);
		//获取视频音频的时间长度
		long duration = 0;//音频长度，毫秒
		try{
			if(item.getExtName().equals("mp3") || item.getExtName().equals("mp4")){
				CommonsMultipartFile cf= (CommonsMultipartFile)file;
		        DiskFileItem fi = (DiskFileItem)cf.getFileItem();
		        File source = fi.getStoreLocation();
		        Encoder encoder = new Encoder();
				MultimediaInfo m = encoder.getInfo(source);
				duration = m.getDuration();
				item.setDuration(duration);
			}
			if(item.getExtName().equals("apk")){
				item.setPath("/resource/apk/");
			}else if(item.getExtName().equals("mp3")){
				item.setContentType("audio/mp3");
				// 文件路径
				item.setPath("/resource/audio/" + DateUtils.format(new Date(), "yy/MM/dd"));
			}else {
				item.setPath("/resource/img/" + DateUtils.format(new Date(), "yy/MM/dd"));
			}
			
			// 创建日期
			item.setCreatedDt(new Date());
			// 状态
			item.setStatus(FileStatusConstant.normal);
			
			OSSClient oSSClient = OSSUtils.getOSSClient();
			String resultStr  = OSSUtils.uploadObject2OSS2(oSSClient, item, in, length);
			if(resultStr != null){
				dao.insert(item);
			}
		}catch (InputFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (EncoderException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void uploadVideo(FileInfo item, InputStream in, long length,MultipartFile file) {
		if (item.getId() == null || item.getId().isEmpty()) {
			item.setId(Utils.uuid());
		}
		String[] names = formatName(item.getOname());
		if (item.getName() == null || item.getName().isEmpty()) {
			item.setName(names[0]);
		}
		item.setExtName(names[1]);
		//获取视频音频的时间长度
		long duration = 0;//音频长度，毫秒
		// 创建日期
		item.setCreatedDt(new Date());
		// 状态
		item.setStatus(FileStatusConstant.normal);
	}
	public static final String uploadObject2OSS2(OSSClient client,FileInfo ofile, InputStream in , long length,String BUCKET_NAME,String path) {
		String resultStr = null;
		//ofile.setPath(DateUtils.format(new Date(), "yy/MM/dd"));
		try {
			// 创建上传Object的Metadata
			ObjectMetadata metadata = new ObjectMetadata();
			// 设置上传文件长度
			metadata.setContentLength(in.available());
			metadata.setCacheControl("no-cache");
			metadata.setHeader("Pragma", "no-cache");
			metadata.setContentEncoding("utf-8");
			metadata.setContentType(ofile.getContentType());//文件类型设置 getContentType(newFilename)
			metadata.setContentDisposition("filename/filesize=" + ofile.getOname() + "/" + length + "Byte.");
			//去掉路径第一个/字符
			//String newFileUploadFullDirectory = ofile.getPath().substring(1,ofile.getPath().length());
			//String path = newFileUploadFullDirectory +"/" +ofile.getId()+"."+ofile.getExtName();
			// 上传文件
			PutObjectResult putResult = client.putObject(BUCKET_NAME, path, in, metadata);
			// 解析结果
			resultStr = putResult.getETag();
			//关闭流
		} catch (Exception e) {
			System.out.println(e.getMessage());
			System.out.println("上传阿里云OSS服务器异常." + e.getMessage());
		}
		return resultStr;
	}
	public GetVideoPlayAuthResponse videoPlayAuth(DefaultAcsClient client) {
	    GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest();
	    request.setVideoId("视频ID");
	    GetVideoPlayAuthResponse response = null;
	    try {
	        response = client.getAcsResponse(request);
	    } catch (ServerException e) {
	        throw new RuntimeException("GetVideoPlayAuthRequest Server failed");
	    } catch (ClientException e) {
	        throw new RuntimeException("GetVideoPlayAuthRequest Client failed");
	    }
	    response.getPlayAuth();              //播放凭证
	    response.getVideoMeta();             //视频Meta信息
	    return response;
	}
	
	public DefaultAcsClient getDefaultAcsClient(){
		 DefaultAcsClient aliyunClient = new DefaultAcsClient(
				    DefaultProfile.getProfile("cn-shanghai","LTAIcYk9Pb08TDqd", "PVFbMsa8WuKeLagpAJLGA2gOcTen1B"));
		 return aliyunClient;
	}
		
		//获取视频上传凭证和地址
	 public CreateUploadVideoResponse createUploadVideo(FileInfo fiInfo) {
		 Map<String, Object> map =new HashMap<String,Object>();
		 String keyId=OSSUtils.getOSSClient().getAccessKeyId();
		 String key= OSSUtils.getOSSClient().getAccessKeySecret();
		  DefaultAcsClient aliyunClient;
		    aliyunClient = getDefaultAcsClient();
	        CreateUploadVideoRequest request = new CreateUploadVideoRequest();
	        CreateUploadVideoResponse response = null;
	        try {
	              /*必选，视频源文件名称（必须带后缀, 支持 ".3gp", ".asf", ".avi", ".dat", ".dv", ".flv", ".f4v", ".gif", ".m2t", ".m3u8", ".m4v", ".mj2", ".mjpeg", ".mkv", ".mov", ".mp4", ".mpe", ".mpg", ".mpeg", ".mts", ".ogg", ".qt", ".rm", ".rmvb", ".swf", ".ts", ".vob", ".wmv", ".webm"".aac", ".ac3", ".acm", ".amr", ".ape", ".caf", ".flac", ".m4a", ".mp3", ".ra", ".wav", ".wma"）*/
	              request.setFileName(fiInfo.getOname());
	              //必选，视频标题
	              request.setTitle(fiInfo.getOname());
	              //可选，分类ID
	              request.setCateId(0);
	              //可选，视频标签，多个用逗号分隔
	              //request.setTags("标签1,标签2");
	              //可选，视频描述
	              //request.setDescription("视频描述");
	              //可选，视频源文件字节数
	              //request.setFileSize(0l);
	              
	              response = aliyunClient.getAcsResponse(request);
	             return response;
	        } catch (ServerException e) {
	              System.out.println("CreateUploadVideoRequest Server Exception:");
	              e.printStackTrace();
	              return response;
	        } catch (ClientException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				 return response;
			} 
	  }
	 
	 
	 
	
	 /**
 String videoId = createUploadVideo(aliyunClient);
  System.out.println("VideoId:" + videoId);
  //当网络异常导致文件上传失败时,可刷新上传凭证后再次执行上传操作
  refreshUploadVideo(aliyunClient, videoId);
	  * **/
	 private static void refreshUploadVideo(DefaultAcsClient client, String videoId) {
	        RefreshUploadVideoRequest request = new RefreshUploadVideoRequest();
	        RefreshUploadVideoResponse response = null;
	        try {
	              request.setVideoId(videoId);
	              response = client.getAcsResponse(request);
	        } catch (ServerException e) {
	              System.out.println("RefreshUploadVideoRequest Server Exception:");
	              e.printStackTrace();
	        } catch (ClientException e) {
	              System.out.println("RefreshUploadVideoRequest Client Exception:");
	              e.printStackTrace();
	        }
	        System.out.println("RequestId:" + response.getRequestId());
	        System.out.println("UploadAuth:" + response.getUploadAuth());
	  }
	 
	 //获取播放凭证
	 public GetVideoPlayAuthResponse getVideoPlayAuth(String videoId) {
		    DefaultAcsClient client = getDefaultAcsClient();
		    GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest();
		    request.setVideoId(videoId);
		    GetVideoPlayAuthResponse response = null;
		    try {
		        response = client.getAcsResponse(request);
		    } catch (ServerException e) {
		        throw new RuntimeException("GetVideoPlayAuthRequest Server failed");
		    } catch (ClientException e) {
		        throw new RuntimeException("GetVideoPlayAuthRequest Client failed");
		    }
		    response.getPlayAuth();              //播放凭证
		    response.getVideoMeta();             //视频Meta信息
		    return response;
		}
	 
}
